home *** CD-ROM | disk | FTP | other *** search
- {
- 3 Files:
-
- PROTCOMM.PAS
- IO.PAS
- BBS.PAS
-
- [-----------protcomm.pas begins----------------------------------------]
- { Origin - Mark Dignam of Omen Technologies This unit has been highly modified }
-
- Unit ProtComm;
-
- Interface
-
- Procedure SetBaud (NewRate : LongInt);
- Function GetBaud : LongInt;
- Function Comm_Init (Baud : LongInt; ThePort : Byte) : Boolean;
- Procedure ModemDeInit;
- Procedure SetDTR (OnOff : Boolean);
- Function SendReady: Boolean;
- Function Carrier : Boolean;
- Function DataAvailable : Boolean;
- Function GetChar : Byte;
- Procedure HangUp;
- Function Ringing : Boolean;
- Procedure SendByte (Ch : Char);
- Procedure AsyncFlushOutput;
- Procedure AsyncPurgeOutput;
- Procedure AsyncPurgeInput;
- Procedure SendBreak;
- Procedure CTS_RTS (OnOff : Boolean);
- Procedure AWrite (S : String);
- Procedure AWriteLn (S : String);
-
- Var CanUseFossil : Boolean;
- UsedPort : Byte;
-
- Implementation
-
- Uses Crt, { Borland CRT Routines }
- Dos; { Borland Disk I/O Routines }
-
- Const MaxPhysPort = 7;
- BufferSize = 8196;
- BufferMax = 8195;
- CommInterrupt = $14 ;
- I8088_IMR = $21 ; { port address of the Interrupt Mask Register }
- IBM_UART_THR = $00 ;
- IBM_UART_RBR = $00 ;
- IBM_UART_IER = $01 ;
- IBM_UART_IIR = $02 ;
- IBM_UART_LCR = $03 ;
- IBM_UART_MCR = $04 ;
- IBM_UART_LSR = $05 ;
- IBM_UART_MSR = $06 ;
- PortTable : Array [0..MaxPhysPort] Of Record
- Base : Word;
- IRQ : Byte
- End = ( (Base : $3F8; IRQ : 4),
- (Base : $2F8; IRQ : 3),
- (Base : $3E8; IRQ : 4),
- (Base : $2E8; IRQ : 3),
- (Base : 0; IRQ : 0),
- (Base : 0; IRQ : 0),
- (Base : 0; IRQ : 0),
- (Base : 0; IRQ : 0));
-
- Var BIOS_Ports, IRQ : Byte;
- Old_IER, Old_IIR, Old_LCR, Old_MCR, Old_IMR : Byte;
- ExitSave, OriginalVector : Pointer;
- IsOpen, OverFlow, UseFossil, CTS_RTS_On : Boolean;
- Base, BufferHead, BufferTail, BufferNewTail : Word;
- Status, RxWord, CtsTimer : Word;
- Buffer : Array [0..BufferMax] Of
- Byte; Regs : Registers;
-
- Procedure Comm_SetBios (NewRate : LongInt);
- Var BaudRate : Byte;
- Temp0 : Integer;
- Begin
- {$IFNDEF TEST}
- Temp0 := NewRate Div 10;
- Case Temp0 of
- 30 : BaudRate := $43;
- 60 : BaudRate := $63;
- 120 : BaudRate := $83;
- 240 : BaudRate := $A3;
- 480 : BaudRate := $C3;
- 960 : BaudRate := $E3;
- 1920 : BaudRate := $03;
- 3840 : BaudRate := $23;
- 5760 : BaudRate := $23;
- End;
- Regs.AH := 0;
- Regs.AL := BaudRate;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- {$ENDIF}
- End;
-
- Procedure Comm_SetDirect (NewRate : LongInt);
- Var I, J, K : Word;
- Temp : LongInt;
- Begin
- {$IFNDEF TEST}
- Temp := 115200;
- Temp := Temp DIV Newrate;
- Move (Temp, J, 2);
- K := Port [IBM_UART_LCR + Base];
- port [IBM_UART_LCR + Base] := $80;
- Port [IBM_UART_THR + Base] := Lo (J);
- Port [IBM_UART_IER + Base] := Hi (J);
- Port [IBM_UART_LCR + Base] := 3;
- {$ENDIF}
- End;
-
- Procedure SetBaud (NewRate : LongInt);
- Begin
- {$IFNDEF TEST}
- If UseFossil Then Comm_SetBios (NewRate) Else Comm_SetDirect (NewRate);
- {$ENDIF}
- End;
-
- Function Getbaud : LongInt;
- Var I, J, K : Word;
- Temp : LongInt;
- begin
- {$IFNDEF TEST}
- K := Port [ibm_UART_LCR + Base];
- Port [IBM_UART_LCR + Base] := K OR $80;
- i := Port [IBM_UART_THR + Base];
- J := Port [IBM_UART_IER + Base];
- J := J * $100;
- J := J + I;
- Port [IBM_UART_LCR + base] := k;
- Temp := 115200;
- Temp := Temp DIV J;
- GetBaud := Temp;
- {$ELSE}
- GetBaud := 4800;
- {$ENDIF}
- End;
-
- Function Carrier : Boolean;
- Begin
- {$IFNDEF TEST}
- Carrier := Port [IBM_UART_MSR + Base] AND $80 = $80;
- {$ELSE}
- Carrier := False;
- {$ENDIF}
- End;
-
- Procedure DisableInterrupts; Inline ($FA);
- Procedure EnableInterrupts; Inline ($FB);
-
- Procedure ISR; Interrupt;
- Begin
- {$IFNDEF TEST}
- Inline(
- $FB/ { sti }
- {Start: }
- { get the incoming character }
- { Buffer[BufferHead] := chr(port[base + ibm_uart_rbr]); }
- $8B/$16/Base/ { mov dx,Base }
- $EC/ { in al,dx }
- $8B/$1E/BufferHead/ { mov bx,BufferHead }
- $88/$87/Buffer/ { mov Buffer[bx],al }
- { BufferNewHead := Succ (BufferHead); }
- $43/ { inc bx }
- { if BufferNewHead > BufferMax then BufferNewHead := 0 ; }
- $81/$FB/BufferMax/ { cmp bx,BufferMax }
- $7E/$02/ { jle l001 }
- $33/$DB/ { xor bx,bx }
- { if BufferNewHead = BufferTail then Overflow := true }
- {L001: }
- $3B/$1E/BufferTail/ { cmp bx,BufferTail }
- $75/$07/ { jne L002 }
- $C6/$06/Overflow/$01/ { mov overflow,1 }
- $EB/$0E/ { jmp short L003 }
- { ELSE BEGIN }
- { BufferHead := BufferNewHead; }
- { Async_BufferUsed := succ(Async_BufferUsed); }
- { IF Async_BufferUsed > Async_MaxBufferUsed then }
- { Async_MaxBufferUsed := Async_BufferUsed }
- { END ; }
- {L002: }
- $89/$1E/BufferHead/ { mov BufferHead,bx }
- $83/$C2/$05/ { Add dx,5 }
- { Check FIFO - And process if more bytes. }
- $EC/ { In al,dx }
- $24/$01/ { And al,$01 }
- $3C/$01/ { cmp al,$01 }
- $74/$CF/ { je start: }
- {L003: }
- $FA/ { cli }
- { issue non-specific EOI }
- { port[$20] := $20 ; }
- $B0/$20/ { mov al,20h }
- $E6/$20); { out 20h,al }
- {$ENDIF}
- End;
-
- Procedure Async_Close;
- Begin
- {$IFNDEF TEST}
- If IsOpen Then
- Begin
- DisableInterrupts;
- Port [I8088_IMR] := (Port[I8088_IMR] OR (1 SHL IRQ));
- Port [IBM_UART_IER + Base] := Old_IER;
- EnableInterrupts;
- Port [IBM_UART_MCR + Base] := Old_MCR;
- Port [IBM_UART_LCR + Base] := Old_lCR;
- SetIntVec (IRQ + 8, OriginalVector);
- IsOpen := False;
- End;
- {$ENDIF}
- End;
-
- Function Init_fossil (Baud : LongInt; ThePort : Byte) : Boolean;
- Begin
- {$IFNDEF TEST}
- UsedPort := ThePort - 1;
- Regs.AH := 4;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- If Regs.AX <> $1954 Then Init_Fossil := False Else
- Begin
- Init_Fossil := True;
- UseFossil := True;
- SetBaud (Baud);
- End;
- {$ELSE}
- Init_Fossil := True;
- {$ENDIF}
- End;
-
- Function Async_Open(Baud : Longint; LogicalPortNum: byte): boolean;
- Var I, OldIIR : Byte;
- Fifos, PortThere : Boolean;
- Begin
- {$IFNDEF TEST}
- If Not IsOpen Then
- Begin
- BufferHead := 0;
- BufferTail := 0;
- Overflow := False;
- UsedPort := Pred (LogicalPortNum);
- Fifos := False;
- IsOpen := False;
- If PortTable [UsedPort].Base <> 0 Then
- Begin
- Base := PortTable [UsedPort].Base;
- IRQ := PortTable [UsedPort].IRQ;
- Old_IER := Port [IBM_UART_IER + Base];
- Old_MCR := Port [IBM_UART_MCR + Base];
- Old_LCR := Port [IBM_UART_LCR + Base];
- Port [IBM_UART_LCR + Base] := $75;
- PortThere := (Port [IBM_UART_LCR + Base] = $75);
- Port [IBM_UART_LCR + Base] := $3;
- If PortThere Then
- Begin
- Comm_SetDirect (Baud);
- Port [IBM_UART_MCR + Base] := $0B;
- OldIIR := Port [IBM_UART_IIR + Base];
- Port [IBM_UART_IIR + Base] := 1;
- Fifos := (Port [IBM_UART_IIR + Base] AND $C0 = $C0);
- If Not Fifos Then Port [IBM_UART_IIR + Base] := OldIIR;
- GetIntVec (IRQ + 8, OriginalVector);
- SetIntVec (IRQ + 8, @ISR);
- DisableInterrupts;
- Port [I8088_IMR] := (Port [I8088_IMR] AND ((1 SHL IRQ) XOR $FF));
- Port [IBM_UART_IER + Base] := 1;
- EnableInterrupts;
- IsOpen := True;
- End;
- End;
- End;
- Async_Open := IsOpen
- {$ELSE}
- Async_Open := True;
- {$ENDIF}
- End;
-
- {$F+}
- Procedure TerminateUnit;
- {$F-}
-
- Begin
- Async_Close;
- ExitProc := ExitSave
- End;
-
- Function Comm_init (Baud : Longint; ThePort : Byte) : Boolean;
- Begin
- {$IFNDEF TEST}
- UseFossil := False;
- If Not IsOpen Then
- Begin
- If (CanUseFossil) AND (Init_Fossil (Baud, ThePort)) Then
- Begin
- Comm_Init := True;
- IsOpen := True;
- Base := PortTable [UsedPort].Base;
- End Else
- Begin
- If Async_Open (Baud, ThePort) Then
- Begin
- Comm_Init := true;
- IsOpen := True;
- End Else Comm_Init := False;
- End;
- End;
- UsedPort := ThePort;
- {$ELSE}
- Comm_Init := True;
- {$ENDIF}
- End;
-
- Function DataAvailable : Boolean;
- Var AHigh : Byte;
- Begin
- {$IFNDEF TEST}
- If UseFossil Then
- Begin
- Inline ($B4/$03/ { MOV AH, 3 }
- $8b/$16/UsedPort/ { MOV DX, Usedport }
- $cd/$14/ { INT 14h }
- $a3/Status); { MOV [Status], AL }
- DataAvailable := ((Status AND $100) <> 0);
- End Else DataAvailable := (Bufferhead <> BufferTail);
- {$ELSE}
- DataAvailable := False;
- {$ENDIF}
- End;
-
- Procedure ModemDeInit;
- Begin
- {$IFNDEF TEST}
- If IsOpen Then
- Begin
- If UseFossil Then
- Begin
- Regs.AH := 5;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End Else Async_Close;
- IsOpen := False;
- End;
- {$ENDIF}
- End;
-
- Function GetChar : byte;
- Begin
- {$IFNDEF TEST}
- If UseFossil Then
- Begin
- Inline ($B4/$02/ { MOV AH, 3 }
- $8b/$16/UsedPort/ { MOV Dx, Usedport }
- $CD/$14/ { INT 14h }
- $A3/RXWord); { Mov [Status], AL }
- GetChar := Lo (RXWord);
- End Else
- Begin
- GetChar := Buffer [BufferTail] ;
- BufferTail := (Succ (BufferTail) MOD BufferSize) ;
- End;
- {$ENDIF}
- End;
-
- Function SendReady : boolean;
- Var Ahigh : Byte;
- Carr, CTS, THR : boolean;
- Begin
- {$IFNDEF TEST}
- If UseFossil Then
- Begin
- Inline ($B4/$03/ { MOV AH, 3 }
- $8B/$16/UsedPort/ { MOV DX, Usedport }
- $CD/$14/ { INT 14h }
- $A3/Status); { MOV Status, AX }
- THR := (Status AND $2000) <> 0;
- Carr := (Status AND $0080) <> 0;
- SendReady := THR OR (Not Carr);
-
- End Else
- Begin
- THR := ((Port [IBM_UART_LSR + Base] AND $20) <> 0);
- CTS := (Port [IBM_UART_MSR + Base] AND $10 = $10);
- If CTS_RTS_On AND Carrier Then SendReady := THR AND Cts Else SendReady :=
- THR; End;
- {$ELSE}
- SendReady := False;
- {$ENDIF}
- End;
-
- Procedure SendByte (Ch : Char);
- Begin
- {$IFNDEF TEST}
- Repeat Until SendReady;
- If UseFossil then
- Begin
- Regs.AH := 1;
- Regs.AL := Ord (Ch);
- Regs.DX := UsedPort;
- intr($14,regs);
- End Else Port [IBM_UART_THR + Base] := Ord (Ch);
- {$ENDIF}
- End;
-
- Procedure AsyncFlushOutput;
- Begin
- {$IFNDEF TEST}
- If Usefossil Then
- Begin
- Regs.AH := 8;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End;
- {$ENDIF}
- End;
-
-
- Procedure AsyncPurgeOutput;
- Begin
- {$IFNDEF TEST}
- If UseFossil Then
- Begin
- Regs.AH := 9;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End;
- {$ENDIF}
- End;
-
- Procedure AsyncPurgeInput;
- Begin
- {$IFNDEF TEST}
- If UseFossil then
- Begin
- Regs.AH := $0A;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End Else
- Begin
- BufferHead := 0;
- BufferTail := 0;
- OverFlow := False;
- End;
- {$ENDIF}
- End;
-
- Procedure SendBreak;
- Var I, J : Byte;
- Begin
- {$IFNDEF TEST}
- If UseFossil then
- Begin
- Regs.AX := $1A01;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- Delay (100);
- Regs.AX := $1A00;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End Else
- Begin
- I := Port [IBM_UART_LCR + Base];
- J := I;
- I := I AND $7F;
- I := I OR $40;
- Port [IBM_UART_LCR + Base] := I;
- delay (100);
- Port [IBM_UART_LCR + Base] := J;
- End;
- {$ENDIF}
- End;
-
- Procedure SetDTR (OnOff : Boolean);
- Var I : Byte;
- Begin
- {$IFNDEF TEST}
- If UseFossil then
- Begin
- Regs.AH := $06;
- If OnOff Then Regs.AL := 1 Else Regs.AL := 0;
- Regs.DX := UsedPort;
- Intr ($14, Regs);
- End Else
- Begin
- If OnOff Then Port [IBM_UART_MCR + Base] := $0B Else Port [IBM_Uart_MCR +
- Base] := $0A; End;
- {$ENDIF}
- End;
-
- Procedure CTS_RTS (OnOff : Boolean);
- Begin
- {$IFNDEF TEST}
- If UseFossil Then
- Begin
- Regs.DX := UsedPort;
- If OnOff Then Regs.AL := 2 Else Regs.AL := 0;
- Regs.AH := $0F;
- Intr ($14, Regs);
- End Else CTS_RTS_On := OnOff;
- {$ENDIF}
- End;
-
- Procedure AWrite (S : String);
- Var I : Integer;
- Begin
- {$IFNDEF TEST}
- For I := 1 To Length (S) Do SendByte ((S[I]));
- {$ENDIF}
- End;
-
- Procedure AWriteLn (S : String);
- Begin
- {$IFNDEF TEST}
- AWrite (S + #10#13);
- {$ENDIF}
- End;
-
- Function Ringing : Boolean;
- Begin
- {$IFNDEF TEST}
- Case UsedPort of
- 1 : Ringing := Boolean (Port[$3FE] And 64);
- 2 : Ringing := Boolean (Port[$2FE] And 64);
- 3 : Ringing := Boolean (Port[$3EE] And 64);
- 4 : Ringing := Boolean (Port[$2EE] And 64);
- Else Ringing := False;
- End;
- {$ELSE}
- Ringing := False;
- {$ENDIF}
- End;
-
- Procedure Hangup;
- Begin
- {$IFNDEF TEST}
- SetDTR (False);
- Delay (250);
- SetDTR (True);
- {$ENDIF}
- End;
-
- Begin
- {$IFNDEF TEST}
- ExitSave := ExitProc;
- ExitProc := @TerminateUnit;
- IsOpen := FALSE;
- Overflow := FALSE;
- CanUseFossil := False;
- CTS_RTS_On := True;
- Bios_Ports := 4;
- {$ENDIF}
- End.
-
- [-----------protcomm.pas ends -------------------------------------------------]
- [-----------io.pas begins-----------------------------------------------------]
- Unit IO;
-
- Interface
-
- Procedure SWrite (S : String);
- Procedure SWriteLn (S : String);
- Procedure SReadLn (Var S : String);
- Procedure SClrScr;
-
- Var Local : Boolean;
-
- Implementation
-
- Uses Crt, ProtComm;
-
- Procedure SWrite (S : String);
- Begin
- Write (S);
- If Not Local Then AWrite (S);
- End;
-
- Procedure SWriteLn (S : String);
- Begin
- WriteLn (S);
- If Not Local Then AWriteLn (S);
- End;
-
- Function SReadKey : Char;
- Var Done : Boolean;
- Ch : Char;
- Begin
- Done := False;
- Repeat
- If (Not Local) and (Not Carrier) Then Done := True;
- If Not Local Then
- If DataAvailable Then
- Begin
- Ch := Chr (GetChar);
- Done := True;
- End;
- If KeyPressed Then
- Begin
- Ch := ReadKey;
- Done := True;
- End;
- Until Done;
- SReadKey := Ch;
- End;
-
- Function SKeyPressed : Boolean;
- Begin
- SKeyPressed := False;
- If DataAvailable Then SKeyPressed := True;
- If KeyPressed Then SKeyPressed := True;
- End;
-
- Procedure SReadLn (Var S : String);
- Var Ch : Char;
- Begin
- S := '';
- Repeat
- Ch := SReadKey;
- If Ord (Ch) in [32..122] Then
- Begin
- S := S + Ch;
- SWrite (Ch);
- End;
- If Ord (Ch) = Ord (8) Then
- Begin
- If Length (S) > 0 Then
- Begin
- SWrite (#8' '#8);
- Delete (S, Length (S), 1);
- End;
- End;
- Until (Ord (Ch) = 13) OR ((Not Carrier) AND (Not Local));
- SWrite (#13#10);
- End;
-
- Procedure SClrScr;
- Begin
- SWriteLn (#12);
- ClrScr;
- End;
-
- End.
- [-----------io.pas ends-------------------------------------------------]
- [-----------bbs.pas begins ---------------------------------------------]
- { Minimal BBS - part of the Communications Package of HTCPACK #7
- For more information or for information on where to obtain complete
- HTCPACK's email havoc.the.chaos@iirg.com }
-
- Uses Crt, IO, ProtComm;
-
- Var TestPad : String;
- OutChar : Char;
-
- Procedure RunBBS;
- Var Answer : String;
- Begin
- SWriteLn ('Welcome to the minimal BBS!');
- SWrite ('Type somethin: ');
- SReadLn (Answer);
- SWriteLn ('You typed "' + Answer + '"');
- Delay (5000);
- SWriteLn ('Goodbye!');
- AsyncFlushOutput;
- Hangup;
- End;
-
- Procedure FrontEnd;
- Var EscPressed : Boolean;
- ModemString : String;
- Timer : Integer;
- Ch : Char;
- Begin
- If Not Local Then AWriteLn ('ATA');
- ClrScr;
- WriteLn ('*** RING ***'#7);
- ModemString := '';
- EscPressed := False;
- If Not Local Then
- Begin
- AsyncPurgeInput;
- Timer := 0;
- EscPressed := False;
- Repeat
- ModemString := '';
- While DataAvailable Do ModemString := ModemString + Chr (GetChar);
- Delay (1);
- Inc (Timer);
- If KeyPressed Then
- Begin
- Ch := ReadKey;
- If Ord (Ch) = Ord (27) Then EscPressed := True;
- End;
- Until (Carrier) or (Timer = 60000) or (Local) or (EscPressed);
- End;
- If EscPressed OR (Timer = 60000) Then
- Begin
- ClrScr;
- AWriteLn ('');
- Write ('Connection not established due to ');
- If EscPressed Then WriteLn ('local escape.');
- If Timer = 60000 Then WriteLn ('a 60 time elapse with no connection.');
- Delay (2000);
- Exit;
- End;
- If Carrier OR Local Then
- Begin
- While KeyPressed Do Write (ReadKey, #8);
- AsyncPurgeInput;
- RunBBS;
- End;
- End;
-
- Procedure Initialize;
- Begin
- Comm_Init (57600, 2);
- ClrScr;
- Local := False;
- AsyncPurgeInput;
- While DataAvailable Do Write (Chr (GetChar));
- If Not Carrier Then AWriteLn ('ATZ');
- End;
-
- Begin
- Initialize;
- Repeat
- TestPad := '';
- While DataAvailable Do
- Begin
- TestPad := TestPad + Chr (GetChar);
- End;
- TestPad := '';
- If Ringing Then
- Begin
- Local := False;
- FrontEnd;
- End;
- If KeyPressed Then
- Begin
- OutChar := ReadKey;
- Case Ord (OutChar) of
- 0 : Begin
- OutChar := ReadKey;
- Case Ord (OutChar) of
- {F1} 59 : Begin
- Local := True;
- FrontEnd;
- End;
- {ALT-X} 45 : Begin
- ModemDeInit;
- Halt;
- End;
- End;
- End;
- End;
- End;
- Until 1 = 2;
- End.
-
- [-----------bbs.pas ends-------------------------------------------------]